<?xml version="1.0" encoding="utf-8"?>
<!--
    SVN Graph Branches
    Copyright © 2010 Olivier Mengué

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-->
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:strip-space elements="forest tree"/>
  <xsl:output method="text"/>

  <xsl:key name="rev-refs" match="//forest/tree/@revision | //forest/tree/@last-changed-rev | //forest/tree/@last-changed-rev-before | //forest/tree/@deleted-rev" use="."/>
  <xsl:key name="branch-revs-external" match="//forest/tree/@last-changed-rev-before" use="../@from-path"/>

  <!-- We have multiple trees for a given path when a path has been deleted and recreated -->
  <xsl:key name="trees-by-path" match="//forest/tree" use="@path"/>

  <xsl:variable name="global-last-rev">
    <xsl:for-each select="//tree/@last-changed-rev">
      <xsl:sort select="." data-type="number" order="descending"/>
      <xsl:if test="position() = 1">
        <xsl:value-of select="number(.)"/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>

  <xsl:template match="//forest">
    <xsl:variable name="title">
      <xsl:apply-templates select="." mode="title"/>
    </xsl:variable>

    digraph "<xsl:value-of select="$title"/>" {
      label = "<xsl:value-of select="$title"/>";
      fontname = "Lucida Console";
      node [
        fontname = "Lucida Console"
      ];
      edge [
        fontname = "Lucida Console"
      ];

      /* Branches */
      <xsl:for-each select="tree">
        <xsl:sort select="@revision" data-type="number" order="ascending"/>

        <xsl:variable name="graph-attrs">
          <xsl:choose>
            <xsl:when test="@last-changed-rev = @revision"><!-- tag -->
              color=blue shape=note
            </xsl:when>
            <xsl:otherwise><!-- Definition of a branch -->
              color=green shape=box
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:variable name="tooltip">
          <xsl:apply-templates select="." mode="tooltip"/>
        </xsl:variable>

        /* <xsl:value-of select="@path"/> */
        subgraph "cluster_<xsl:value-of select="concat(@path, ' r', @revision)"/>" {
          graph [
            label = "<xsl:value-of select="@path"/>" <xsl:value-of select="$graph-attrs"/>
          ];

          <xsl:variable name="path" select="@path"/>
          <xsl:variable name="first-rev" select="number(@revision)"/>
          <xsl:variable name="last-rev" select="number(@last-changed-rev)"/>

          r<xsl:value-of select="$first-rev"/> [ tooltip = "<xsl:value-of select="$tooltip"/>" ];

          <xsl:if test="$last-rev != $first-rev">

                 r<xsl:value-of select="$first-rev"/>

          <xsl:variable name="revs" select="key('branch-revs-external', $path)[number(.) &gt; $first-rev and number(.) &lt; $last-rev]"/>
          <xsl:variable name="distinct-revs" select="$revs[count(. | key('rev-refs', .)[1]) = 1]"/>

            <xsl:for-each select="$distinct-revs">
              <xsl:sort select="." data-type="number" order="ascending"/>
              -&gt; r<xsl:value-of select="."/>
            </xsl:for-each>

              -&gt; r<xsl:value-of select="$last-rev"/>
              ;
          </xsl:if>

          <xsl:if test="@deleted-rev">
              <xsl:variable name="delete-node" select="concat('delete ', $path, ' r', $first-rev)"/>
              "<xsl:value-of select="$delete-node"/>" [ label = "r<xsl:value-of select="@deleted-rev"/>" ];
              r<xsl:value-of select="$last-rev"/>
              -&gt; "<xsl:value-of select="$delete-node"/>"
                [ label = "delete" style = dotted ];
          </xsl:if>
        }

        <xsl:if test="@last-changed-rev-before">
            r<xsl:value-of select="@last-changed-rev-before"/> -&gt; r<xsl:value-of select="@revision"/> [ label = "copy" ];
            <!--
            <xsl:variable name="from-rev" select="@from-rev"/>
            <xsl:variable name="from-tree" select="key('trees-by-path', @from-path)[$from-rev &gt;= @revision and $from-rev &lt;= @last-changed-rev ]"/>
            <xsl:if test="$from-rev != @last-changed-rev-before and $from-rev &lt; $from-tree/@last-changed-rev">
            r<xsl:value-of select="@from-rev"/> -&gt; r<xsl:value-of select="@revision"/> [ style = dashed ];
          </xsl:if>
          -->
        </xsl:if>

      </xsl:for-each>
    }
  </xsl:template>

  <xsl:template match="forest[@path]" mode="title">
    <xsl:value-of select="concat(@path, ' @ r', $global-last-rev)"/>
  </xsl:template>

  <xsl:template match="tree" mode="tooltip">
    <xsl:value-of select="concat(substring(date, 1, 10), ' ', author)"/>
    <xsl:if test="not(contains(string(msg), '&#10;'))">
      <!-- GraphViz does not expand \n in tooltip in SVG output :( -->
      <!-- And &#10; doesn't work either :( -->
      <!--<xsl:text>\n</xsl:text>-->
      <xsl:value-of select="string(msg)"/>
    </xsl:if>
  </xsl:template>

  <!-- root of a Google Code-hosted project -->
  <xsl:template match="forest[contains(@url, '.googlecode.com/svn')]" mode="title">
    <xsl:variable name="project" select="substring-after(substring-before(@url, '.googlecode.com/'), '://')"/>
    <xsl:message>Project: <xsl:value-of select="$project"/></xsl:message>
    <!--
    <xsl:value-of select="concat($project, ': ', document(concat('http://code.google.com/p/', $project, '/source/checkout'))//a[@id='project_summary_link'])"/>
    -->
    <xsl:value-of select="concat($project, ' @ r', $global-last-rev)"/>
  </xsl:template>

</xsl:stylesheet><!-- vim:set et ts=4 sw=2 sts=2: -->
